package com.qiyang.interceptor;

import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

/**
 * Created on 2020/12/15.
 *
 * @author qiyang.
 * 描述：实现一个简易版的分页插件
 */
@Intercepts({
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}), // 设置代理的对象
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}) // 设置代理的对象
})
public class MyPageInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {

        System.out.println("实现一个简易版的分页插件");
        // 修改SQL，拼接Limit

        // 获取参数
        Object[] args = invocation.getArgs();

        // 对mapper映射文件元素的封装
        MappedStatement mappedStatement = (MappedStatement) args[0];
        // 对SQL及参数的封装
        Object parameterObject = args[1];

        BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
        // 封装了分页的参数，当前页与页码
        RowBounds rowBounds = (RowBounds) args[2];

        // 拿到原SQL语句
        String sql = boundSql.getSql();
        String limitSql = sql.concat(" LIMIT " + rowBounds.getOffset() + "," + rowBounds.getLimit());

        BoundSql pageBoundSql = new BoundSql(mappedStatement.getConfiguration(), limitSql, boundSql.getParameterMappings(), parameterObject);
        // 获取被代理的对象
        Executor executor = (Executor) invocation.getTarget();

        CacheKey cacheKey = executor.createCacheKey(mappedStatement, parameterObject, rowBounds, pageBoundSql);

        // 调用修改后的SQL，继续执行查询
        return executor.query(mappedStatement, parameterObject, rowBounds, (ResultHandler) args[3], cacheKey, pageBoundSql);
    }
}

